package com.spring.component.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author liushihua
 * @since 2018年03月28日
 */
public class HttpsClientUtil {

  private static final Logger log = LoggerFactory.getLogger(HttpsClientUtil.class);

  /**
   * 设置信任自签名证书
   * 
   * @param keyStorePath 密钥库路径
   * @param keyStorepass 密钥库密码
   * @return
   */
  public static SSLContext custom(String keyStorePath, String keyStorepass) {
    FileInputStream inputStream = null;
    try {
      KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
      inputStream = new FileInputStream(new File(keyStorePath));
      keyStore.load(inputStream, keyStorepass.toCharArray());
      // 相信自己的CA和所有自签名的证书
      SSLContext sc =
          SSLContexts.custom().loadTrustMaterial(keyStore, new TrustSelfSignedStrategy()).build();
      TrustManagerFactory managerFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
      managerFactory.init(keyStore);
      TrustManager[] trustManagers = managerFactory.getTrustManagers();
      SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
      sslContext.init(null, trustManagers, new SecureRandom());
      return sslContext;
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        inputStream.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return null;
  }

  public static String post(String url, Map<String, String> params, Map<String, String> headers) {
    SSLContext sslContext =
        custom("C:\\Program Files\\Java\\jdk1.8.0_152\\jre\\lib\\security\\cacerts", "changeit");
    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
        .<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
        .register("https", new SSLConnectionSocketFactory(sslContext)).build();
    PoolingHttpClientConnectionManager connectionManager =
        new PoolingHttpClientConnectionManager(socketFactoryRegistry);
    CloseableHttpClient client =
        HttpClientBuilder.create().setConnectionManager(connectionManager).build();
    HttpPost httpPost = new HttpPost(url);
    try {
      if (CollectionUtil.isNotBlank(headers)) {
        headers.forEach((k, v) -> httpPost.setHeader(k, v));
      }
      if (CollectionUtil.isNotBlank(params)) {
        List<NameValuePair> nameValuePairs = new ArrayList<>();
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        params.forEach((k, v) -> nameValuePairs.add(new BasicNameValuePair(k, v)));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
      }
      CloseableHttpResponse response = client.execute(httpPost);
      int statusCode = response.getStatusLine().getStatusCode();
      if (statusCode != 200) {
        httpPost.abort();
        throw new RuntimeException("HttpsClient,error status code :" + statusCode);
      } else {
        HttpEntity entity = response.getEntity();
        String result = EntityUtils.toString(entity, "UTF-8");
        EntityUtils.consume(entity);
        client.close();
        return result;
      }
    } catch (Exception e) {
      log.error("调用httpsClient错误，url：{}--------{}", httpPost.getURI(), e.getMessage());
      return null;
    }
  }

}
